package org.zkoss.zk.ui;

import java.util.Comparator;
import java.util.List;
import javax.annotation.Resource;

import org.ceva.training.persistence.bo.User;
import org.ceva.training.persistence.dao.UsersDAO;
import org.springframework.context.ApplicationContext;
import org.ceva.training.service.UserModel;
import org.zkoss.lang.Strings;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.KeyEvent;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.FieldComparator;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Spinner;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

import org.zkoss.zkplus.databind.BindingListModel;
import org.zkoss.zkplus.databind.BindingListModelList;
import org.zkoss.zkplus.databind.DataBinder;
import org.zkoss.zkplus.spring.SpringUtil;

public class UserWindow  extends GenericForwardComposer {
	//ZK databinder
	protected DataBinder binder;

	//User Model
	@Resource
	protected UserModel userModel = null;
	
	//main control window
	@Resource
	protected Window UserWnd; //main window
	@Resource
	protected Listbox userList; //domain object summary list
	@Resource
	protected Component userDetail; //domain object detail
	
	//edit mode
	@Resource
	protected Component userEdit; //edit panel
	@Resource
	protected Textbox firstname;
//	@Resource
//	protected Datebox date;
//	@Resource
//	protected Spinner priority;
	
	//buttons
	@Resource
	protected Button userCreate; //new button
	@Resource
	protected Button userUpdate; //edit button
	@Resource
	protected Button userDelete; //delete button
	@Resource
	protected Button userSave; //save button
	@Resource
	protected Button userCancel; //cancel button

	//operation transient state
	protected User _tmpSelected; //store original selected entity
	protected boolean _create; //when new a entity
	protected boolean _editMode; //switch to edit mode when doing editing(new/update)
	protected int _lastSelectedIndex = -1; //last selectedIndex before delete
	
	
	
	public UserModel getUserModel() {
		return userModel;
	}

	public void setModel(UserModel UserModel) {
		this.userModel = UserModel;
	}
	
	public void refreshModel() {
		binder.loadAttribute(userList, "model"); //reload model to force refresh
	}

	//-- view/edit mode --//
	public void setEditMode(boolean b) {
		_editMode = b;
		switchMode();
	}
	
	public boolean isViewMode() {
		return !_editMode;
	}
	public boolean getViewMode() {
		return !_editMode;
	}
	
	public boolean isEditMode() {
		return _editMode; 
	}

	public boolean isCreate() {
		return _create;
	}
	
	public boolean isNotSelected() {
		return this.userModel.getSelected() == null;
	}

	private void switchMode() {
		binder.loadComponent(userDetail); //reload visible to force refresh
		setFocus();
	}
	
	private void setFocus() {
		if (_editMode) {
			firstname.focus();
		} else {
			if (((List)userList.getModel()).isEmpty()) {
				//no result in list, focus on new button
				userCreate.focus();
			} else {
				if (_create) {
					userCreate.focus();
				} else {
					userList.focus();
				}
			}
		}
	}
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		
		ApplicationContext ctx = SpringUtil.getApplicationContext();
		UsersDAO userDAO = (UsersDAO) ctx.getBean("UsersDAO");	
		userModel = new UserModel();
		userModel.setDAO(userDAO);
		userModel.setMaxResults(25);
		List model = (List)userDAO.findAll();
		
		if (!model.isEmpty()) {		
			BindingListModelList bindmodel = new BindingListModelList(model,true);						
			userModel.setSelected((User)bindmodel.get(0));
			//userList.setModel(bindmodel);		
		}
		
		//setFocus();
	}
	//-- Initialization --//
//	@On("UserWin.onCreate")
	public void onWinCreate() {
		
		
		ApplicationContext ctx = SpringUtil.getApplicationContext();
		UsersDAO userDAO = (UsersDAO) ctx.getBean("UsersDAO");	
		userModel = new UserModel();
		userModel.setDAO(userDAO);
		userModel.setMaxResults(25);
		List model = (List)userDAO.findAll();
		
		if (!model.isEmpty()) {		
			BindingListModelList bindmodel = new BindingListModelList(model,true);
			//userModel.setSelected((User)bindmodel.get(0));
			userList.setModel(bindmodel);
		}
		
		setFocus();
	}
	
	//-- view mode control --//
//	@On("UserWnd.onCtrlKey")
	public void onCtrlKey(Event event) {
		final List items = userList.getItems(); 
		if (!items.isEmpty() && (!_editMode || !_create)) {
			final int keycode = ((KeyEvent) event).getKeyCode();
			if (keycode == KeyEvent.DOWN || keycode == KeyEvent.UP){
				//handle no selected item case
				if (userList.getSelectedIndex() < 0) { //no selected item
					//try our best to guess one
					if (_lastSelectedIndex >= 0) {
						final int index = Math.min(items.size() - 1, _lastSelectedIndex);
						userList.setSelectedIndex(index);
						Events.sendEvent(new SelectEvent("onSelect", userList, userList.getSelectedItems()));
					}
				}
				userList.focus();
			}
		}
	}
	
//@On("userList.onSelect")
	public void onSelect(Event event) {
		final int index = userList.getSelectedIndex();
		if (index >= 0) {
			_lastSelectedIndex = index;
			_create = false;
		}
	}
	
//	@On("userCreate.onClick")
	public void onUserCreate(Event event) {
		if (getViewMode()) {
			//prepare a new User
			_tmpSelected = userModel.getSelected();
			_create = true;
			userModel.setSelected(new User());
			
			//switch to edit mode
			setEditMode(true);
		}
	}
	
//	@On("userUpdate.onClick")
	public void onUpdate(Event event) {
		if (getViewMode()) {
			if (userModel.getSelected() != null) {
				_create = false;

				//switch to edit mode
				setEditMode(true);
			}
		}
	}
	
//	@On("userDelete.onClick")
	public void onDelete(Event event) {
		if (getViewMode()) {
			if (userModel.getSelected() != null) {
				_create = false;
				newConfirmDelete().show();
			}
		}
	}
	
	//-- sorting --//
//	@On("userFirstNameSort.onSort,userLastNameSort.onSort,userRoleSort.onSort")
	public void onSort(Event event) {
		final Listheader lh = (Listheader) event.getTarget();
		final String sortDirection = lh.getSortDirection(); //original direction
		if ("ascending".equals(sortDirection)) {
			final Comparator cmpr = lh.getSortDescending();
			if (cmpr instanceof FieldComparator) {
				final String orderBy = ((FieldComparator)cmpr).getOrderBy();
				userModel.setOrderBy(orderBy); //update query string
			}
		} else if ("descending".equals(sortDirection) || "natural".equals(sortDirection) || Strings.isBlank(sortDirection)) {
			final Comparator cmpr = lh.getSortAscending();
			if (cmpr instanceof FieldComparator) {
				final String orderBy = ((FieldComparator)cmpr).getOrderBy();
				userModel.setOrderBy(orderBy); //update query string
			}
		}
	}
	
	//-- edit mode control --//
//	@On("userSave.onClick,UserWin.onOK")
	public void onSave(Event event) {
		if (isEditMode()) {
			//validate
			validate();

			//save into bean
			binder.saveComponent(userEdit); //reload model to force refresh
			
			//store into db
			if (_create) {
				this.userModel.persist();
			} else {
				try {
					this.userModel.merge();
				} catch (Exception e1) {
					try {
						Messagebox.show(getUpdateDeletedMessage());
					} catch (InterruptedException e2) {
						//ignore
					}
				}
			}
			//refresh the userList
			refreshModel();
			//switch to view mode
			setEditMode(false);
		}
	}

//	@On("userCancel.onClick,UserWin.onCancel")
	public void onCancel(Event event) {
		if (isEditMode()) {
			//restore to original selected User if cancel from new
			if (_create) {
				userModel.setSelected(_tmpSelected);
				_tmpSelected = null;
			}
			
			//switch to view mode
			setEditMode(false);
		}
	}
	
	//--To be override--// 
	/** Validate the input field */
	protected void validate() {
		//date.getValue();
		//priority.getValue();
		firstname.getValue();
	}
	
	/** The info message when end user trying to update a "deleted" entity. */
	protected String getUpdateDeletedMessage() {
		return "Cannot find the selected item, might have been deleted by others.";
	}
	
	/** Get a instance of ConfirmDelete class */
	protected ConfirmDelete newConfirmDelete() {
		return new ConfirmDelete();
	}
	
	/** Delete Confirmation */
	protected class ConfirmDelete {
		/** Show the ConfirmDelete Messagebox */
		public void show() {
			try {
				Messagebox.show(getMessage(),
				        getTitle(),
				        Messagebox.YES+Messagebox.NO,
				        Messagebox.EXCLAMATION,
				        new org.zkoss.zk.ui.event.EventListener() {
							public void onEvent(Event event) {
								if ("onYes".equals(event.getName())) {
									doYes();
								}
							}
						}
					);
			} catch (InterruptedException ex) {
				//ignore
			}
		}
		
		/** Operation when end user click Yes button in confirm delete Messagebox*/
		public void doYes() {
			try {
				userModel.delete();
				userCreate.focus();		
			} catch (Exception e) { 
				//ignore, already deleted by others
			}
			userModel.setSelected(null);
			//refresh the userList
			refreshModel();
			//update the userDetail
			switchMode();
		}
		
		/** Returns title of confirm deleting Messagebox */
		public String getTitle() {
			return "Are you sure?";
		}

		/** Returns message for confirm deleting Messagbox */
		public String getMessage() {
			return "Are you sure you want to delete the selected item?"; 
		}
	}
}
